package com.gsbelarus.gedemin.lib.sync.protocol;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * Запуск синзронизации по расписанию через сервис.
 */
abstract public class AlarmReceiver extends BroadcastReceiver {

    private Context context;

    public static final String ALARM_SYNC_START = "alarm_sync_start";
    private static final int PENDING_REQUEST_CODE = 1;
    private static final int INTERVAL_UPDATE = 30;
    private PendingIntent pendingIntent;

    /**
     * @param oldDate последняя дата на которой была синхронизация
     * @return дата седующей синхронизации
     */
    abstract public Calendar getNextSyncDate(Calendar oldDate);

    /**
     * @return Intent для запуска сервиса
     */
    abstract public Intent getServiceIntent();

    /**
     * @return в демо режиме автосинхронизация не будет срабатывать
     */
    abstract public boolean isWorkMode();

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("AlarmReceiver", "do");
        this.context = context;
        if (intent.getBooleanExtra(ALARM_SYNC_START, false)) {

            pendingIntent = getPendingIntent(PendingIntent.FLAG_NO_CREATE);
            if (pendingIntent != null)
                pendingIntent.cancel();

            if (isWorkMode()) {
                Intent intentService = getServiceIntent();
                intentService.putExtra(SyncProtocolServiceModel.STATUS_SYNC, SyncProtocolServiceModel.DO_SYNC_SCHEDULE);
                context.startService(intentService);
            }
        }

        Calendar date = Calendar.getInstance();
        date.set(Calendar.MINUTE, 0);
        date.set(Calendar.SECOND, 0);
        date.set(Calendar.MILLISECOND, 0);

        setUpdate(getNextSyncDate(date));
    }

    private void setUpdate(Calendar cal) {
        /** создаем PendingIntent который затрет предыдущий */
        pendingIntent = getPendingIntent(PendingIntent.FLAG_NO_CREATE);
        if (pendingIntent != null) {
            Log.d("AlarmReceiver: Следующее обновление", "уже установлено");
            return;
        } else
            pendingIntent = getPendingIntent(PendingIntent.FLAG_CANCEL_CURRENT);

        /** выбираем случайное время (в перделах INTERVAL_UPDATE), что бы не нагружать сервер*/
        cal.add(Calendar.MINUTE, (int) (Math.random() * INTERVAL_UPDATE));

        /** выставляем время в будильнике */
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);

        Log.d("AlarmReceiver: Следующее обновление", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cal.getTimeInMillis()));
    }

    /**
     * получить pendingIntent с определенным флагом
     * *********************************
     * PendingIntent.FLAG_NO_CREATE - если в системе есть pendingIntent с таким intent, то возвращает его.
     * если в системе нет pendingIntent с таким intent, возвращает null
     * *********************************
     * PendingIntent.FLAG_CANCEL_CURRENT - если в системе уже есть pendingIntent с таким intent, pendingIntent полностью пересоздается
     * *********************************
     * PendingIntent.FLAG_UPDATE_CURRENT - если в системе уже есть pendingIntent с таким intent, новый не создается,
     * а его intent помещается в старый
     * *********************************
     */
    private PendingIntent getPendingIntent(int flag) {
        return PendingIntent.getBroadcast(context, PENDING_REQUEST_CODE, new Intent(context, this.getClass()).putExtra(ALARM_SYNC_START, true), flag);
    }

    public Context getContext() {
        return context;
    }
}
